#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <arpa/inet.h>

#include "common.h"


#define __DEBUG_LEN     (2048)
#define __FMT_LOGS(buf, size) \
    do { \
        va_list args; \
        buf[0] = 0; \
        va_start(args, format); \
        (void)vsnprintf(buf, (const unsigned int)size, format, args); \
        va_end(args); \
    } while (0)

void debug_logs(const char* format, ...)
{
    char buf[__DEBUG_LEN];

    __FMT_LOGS(buf, __DEBUG_LEN);
    printf("DEBUG: %s", buf);
}

void info_logs(const char* format, ...)
{
    char buf[__DEBUG_LEN];

    __FMT_LOGS(buf, __DEBUG_LEN);
    printf("INFO: %s", buf);
}

void warn_logs(const char* format, ...)
{
    char buf[__DEBUG_LEN];

    __FMT_LOGS(buf, __DEBUG_LEN);
    printf("WARN: %s", buf);
}

void error_logs(const char* format, ...)
{
    char buf[__DEBUG_LEN];

    __FMT_LOGS(buf, __DEBUG_LEN);
    printf("ERROR: %s", buf);
}

static void ip6_str(unsigned char *ip6, unsigned char *ip_str, unsigned int ip_str_size)
{
    unsigned short *addr = (unsigned short *)ip6;

    /*
      parse ipv4 from ipv6 if the ipv6_addr is ipv4_addr mapped
      eg: [0000...0000:ffff:192.168.1.23] -> [192.168.1.23]
     */
    if (NIP6_IS_ADDR_V4MAPPED(addr)) {
        (void)snprintf((char *)ip_str, ip_str_size, "%u.%u.%u.%u",
                       ip6[IP4_BYTE_1_IN_IP6], ip6[IP4_BYTE_2_IN_IP6], ip6[IP4_BYTE_3_IN_IP6], ip6[IP4_BYTE_4_IN_IP6]);
        return;
    }

    inet_ntop(AF_INET6, (const void *)ip6, (char *)ip_str, ip_str_size);
}

void ip_str(unsigned int family, unsigned char *ip, unsigned char *ip_str, unsigned int ip_str_size)
{
    ip_str[0] = 0;

    if (family == AF_INET6) {
        (void)ip6_str(ip, ip_str, ip_str_size);
        return;
    }

    (void)snprintf((char *)ip_str, ip_str_size, "%u.%u.%u.%u",
                   ip[IP4_BYTE_1], ip[IP4_BYTE_2], ip[IP4_BYTE_3], ip[IP4_BYTE_4]);
    return;
}